/*
    Project: OCMF (Operant Chamber Management Framework)
    Version: 1.0
    Author: Copyright (C) 2010, Samuel Delaney & Andrew Harvey
    Licence:
        This file is part of OCMF.

            OCMF is free software: you can redistribute it and/or modify
            it under the terms of the GNU General Public License as published by
            the Free Software Foundation, either version 3 of the License, or
            (at your option) any later version.

            OCMF is distributed in the hope that it will be useful,
            but WITHOUT ANY WARRANTY; without even the implied warranty of
            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
            GNU General Public License for more details.

            You should have received a copy of the GNU General Public License
            along with OCMF.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Experiment.h"
#include "mainwindow.h"

Experiment::Experiment(QString experimentName, QByteArray qByteArray, OcmfServer * ocmfServer) : ActionCollection(NULL)
{
    name = experimentName;
    ownerOcmfServer = ocmfServer;

    QDomDocument xmlDocument;

    //set the content of the xmldocument to the file
    if(!xmlDocument.setContent(qByteArray))return;

    //get the root of the xmldocument
    QDomElement xmlRoot = xmlDocument.documentElement();

    //get all the children nodes of the root (counters and the experiment core)
    QDomNodeList rootNodes = xmlRoot.childNodes();

    //check that the experiment file is properly formed
    if(rootNodes.count() != 4)return;

    //create an empty screen template with specified name
    qDebug("Parsing Screen Template...");
    ExperimentScreenTemplate = new ScreenTemplate(rootNodes.at(0).toElement());

    //get the counters node
    QDomNode countersNode = rootNodes.at(1);

    //get the list of counters within the counters node
    QDomNodeList countersList = countersNode.childNodes();

    //iterate through each of the counters within the list
    qDebug("Parsing Counters...");
    for(int i = 0; i < countersList.count(); i++)
        //create a copy and place in the counters vector
        Counters[countersList.at(i).toElement().attributeNode("Name").value()] = 0;

    //get the images node
    QDomNode imagesNode = rootNodes.at(2);

    //get the list of images within the images node
    QDomNodeList imagesList = imagesNode.childNodes();

    //iterate through each of the images within the list
    qDebug("Parsing Images...");
    for(int i = 0; i < imagesList.count(); i++)
        Images[imagesList.at(i).toElement().attributeNode("Name").value()] = QImage::fromData(QByteArray::fromBase64((const char *)imagesList.at(i).toElement().text()));

    //get the trials list

    QDomNode trialsNode = rootNodes.at(3);

    QDomNodeList trialsList = trialsNode.childNodes();

    //iterate through each of the trials within the list
    qDebug("Parsing Trials...");
    for(int i = 0; i < trialsList.count(); i++)
    {
        qDebug("bang!");
        //call the trial constructor to parse the xml
        Actions.push_back(new Trial(trialsList.at(i).toElement(), NULL));
    }
}

Experiment::~Experiment()
{
    //deconstruct trials vector
    for(int i = 0; i < Actions.count(); i++)
        delete &Actions[i];
}

void Experiment::Do()
{
    //log result
    Action::WriteResult(ToResultXml());

    //setup screen for experiment template
    //((MainWindow *)Owner()->Owner())->SetupScreen(ExperimentScreenTemplate);

    //iterate over each trial in the Actions vector
    for(currentActionIndex = 0; currentActionIndex < Actions.count(); currentActionIndex++)
        //call the do function of each item in actions
        Actions[currentActionIndex]->Do();
}

QDomElement Experiment::ToResultXml()
{
    QDomElement experimentNode;

    //set the tag value
    experimentNode.setTagName("Experiment");

    //set the timestamp attribute
    experimentNode.setAttribute("TimeStamp", TimeStamp.toString(Qt::ISODate));

    //set the experimentid attribute
    experimentNode.setAttribute("Name", name);

    //set the serverid attribute
    experimentNode.setAttribute("ServerId", ServerConfig::GetConfigVariable("ServerId"));

    //return the xml node
    return experimentNode;
}

QByteArray Experiment::GetResultBytes()
{
    //convert the result xml to a byte array to be written into the db
    return QByteArray(Action::GetResultXml().toUtf8());
}

OcmfServer * Experiment::OwnerOcmfServer()
{
    return ownerOcmfServer;
}
